﻿/**
 * @fileOverview This file contains definition of widget classes derived from BaseWidget.
 * @author GUI group 
 * @version 0.9 beta
 */



/**
 *  @class Simple class that allows the user to create an image object and to retrive the HTML code using toString() public method.
 *  Useful when you use parseString method in a widget.
 *  @param {String} img The image url of the image you want to include
 *  @param {String} [alt] The string that contains the alternative text for the image
 *  @param {String} [title] The title value of title property of link
 *  @param {String} [class] The class of link
 *  @param {String} [id] The id of the anchor href
 */
function ImageSt(img,alt,title,class,id){
	var myid = false;    
	var imgClass = false;
	
	/** The Url where the image is
	 * @field
	 * @type String
	 * @see ImageSt#setImageUri
	 */
	this.imgSrc = false;
	var imgAlt = "";
	var imgTitle = "";
	var that = this;
	
	var _setId = function(_id){
	    if(typeof _id == "string"){
		    myid = _id;
	    }
	}
	
	var _setClass = function(_class){
	    if(typeof _class == "string"){
		    imgClass = _class;
	    }
	}
	
	var _setAlt = function(_alt){
	    if(typeof _alt == "string"){
		    imgAlt = _alt;
	    }
	}

	var _setTitle = function(_title){
	    if(typeof _title == "string"){
		    imgTitle = _title;
	    }
	}

	
	var _setImg = function(_img){
	    var regEx = /^([\\\/:a-zA-Z0-9_\-#\[\]\+]+\.[a-zA-Z]{3,})|(http:[\\\/a-zA-Z0-9\._\-#\[\]\+]+\.[a-zA-Z]{3,})$/;
        if(typeof _img == "string" && regEx.test(_img)){
		    that.imgSrc = _img;
	    }else{alert("image uri format error");}
	}
	
	//Actual variables settings
	_setImg(img);
	_setAlt(alt);
	_setClass(class);
	_setId(id);
	_setTitle(title);

	
	/**
	 * Sets the image attribute.
	 * @param {String} src Url of the image
	 * @see ImageSt#imgSrc
	 * @see ImageSt#getImageUri
	 */
	this.setImageUri = function(src){
		_setImg(src);
	}
	/**
	 * Returns the image attribute value.
	 * @returns the image attribute value
	 * @see ImageSt#imgSrc
	 * @see ImageSt#setImageUri
	 */
	this.getImageUri = function(){
		return that.imgSrc;
	}
		
	/**
	 * Sets the alternative image text. 
	 * @param {String} alt Alternative image text
	 * @see ImageSt#setId
	 * @see ImageSt#setTitle
	 * @see ImageSt#setClass
	 */
    this.setAlt = function(alt){
		_setAlt(alt);
	}
	
	/**
	 * Sets the id of the &lt;img&gt; tag  
	 * @param {String} id The id of the element
	 * @see ImageSt#setAlt
	 * @see ImageSt#setTitle
	 * @see ImageSt#setClass
	 */
	this.setId = function(id){
		_setId(id);
	}
	
	/**
	 * Sets the class of the &lt;img&gt; tag  
	 * @param {String} class The value of class element property
	 * @see ImageSt#setAlt
	 * @see ImageSt#setTitle
	 * @see ImageSt#setId
	 */
    this.setClass = function(class){
		_setClass(class);
	}
	
	/**
	 * Sets the title of the &lt;img&gt; tag  
	 * @param {String} title The value of title element property
	 * @see ImageSt#setAlt
	 * @see ImageSt#setClass
	 * @see ImageSt#setId
	 */
	this.setTitle = function(title){
		_setTitle(title);
	}
	
	/**
	 * Returns the html representation of this element 
	 * @example &lt;img  src="image_URL" id="optional id" class="opt class" alt="opt alt" title="opt title" &#47;&gt;   
	 * @returns An html string
	 * @see BaseWidget#render
	 */	
	this.toString = function(){
		var mytemp = "<img ";
		
		if(that.imgSrc){
		    mytemp += "src=\""+that.imgSrc+"\" ";
		}else{
			return -1; // imgSrc isn't set
		}
		
		if(myid){   //id isn't mandatory in img
			mytemp += "id=\""+ myid +"\" ";
		}
		
		if(imgClass){
			mytemp += "class=\""+imgClass +"\" ";
		}
		
		if(imgTitle){
			mytemp += "title=\""+ imgTitle +"\" ";
		}
		
		if(imgAlt){
			mytemp += "alt=\""+ imgAlt +"\" ";
		}
		
		mytemp += "/>";
		return mytemp;
	}
	
}


/**
 *  @class Simple class that allows the user to create a link object and to retrive the HTML code using toString() public method.
 *  Useful when you use parseString method in a widget.
 *  @param {String} id The id of the anchor href
 *  @param {Function|String} src The string that contains link text (the href  value) or Function used as callback for "click event" on link
 *  @param {String} [txt] The text of link or an ImageSt object (output of ImageSt.toString() method will be used as link content)
 *  @param {String} [class] The class of link
 *  @param {String} [title] The title value of title property of link
 */
function LinkSt(id,src,txt,class,title){
	var myid = id;
	var linkClass = false;
	/** The link onclick callback
	 * @field
	 * @type String
	 * @see ImageSt#setJsFun
	 */		
	this.jsref = false;
	/** The Url pointed by the link
	 * @field
	 * @type String
	 * @see ImageSt#setHref
	 */	
	this.href = false;
	var linkTxt = "";
	var linkTitle = "";
	var that = this;
	
	var _setClass = function(_class){
	    if(typeof _class == "string"){
		    linkClass = _class;
	    }
	}
	
	var _setTxt = function(_txt){
	    if(typeof _txt == "string"){
		    linkTxt = _txt;
	    }else if(_txt instanceof ImageSt){
		    linkTxt = _txt.toString();
	    }
	}
	
	var _setTitle = function(_title){
	    if(typeof _title == "string"){
		    linkTitle = _title;
	    }
	}
	
	var _setJsRef = function(_fun){
	    if(typeof _fun == "function"){
		    that.jsref = _fun;
		    that.href = false;
	    }
	}
	
	var _setHRef = function(_src){
	    if(typeof _src == "string"){
		    that.href = _src;
		    that.jsref = false;
	    }
	}
	
	//Actual variables settings
	_setHRef(src);
	_setJsRef(src);
	_setTxt(txt);
	_setClass(class);
	_setTitle(title);
	
	/**
	 * Sets the value of the href link property   
	 * @param {String} src The URL pointed by the link
	 * @see ImageSt#setJsFun 
	 * @see ImageSt#setTitle
	 * @see ImageSt#setClass
	 * @see ImageSt#setId
	 */	
	this.setHref = function(src){
		_setHRef(src);
	}
	
	/**
	 * Sets the function used as callback for "click" event on link  
	 * @param {String} fun The callback function
	 * @see ImageSt#setHref
	 * @see ImageSt#setTitle
	 * @see ImageSt#setClass
	 * @see ImageSt#setId
	 */
	this.setJsFun = function(fun){
		_setJsRef(fun);
	}
	
	/**
	 * Sets the class of the &lt;a&gt; link tag  
	 * @param {String} class The value of class element property
	 * @see ImageSt#setTitle
	 * @see ImageSt#setId
	 */
    this.setClass = function(class){
		_setClass(class);
	}
	
	/**
	 * Sets the link content. Link content can be a text string or an image    
	 * @param {String|ImageSt} txt The text of the link or the ImageSt object with the image you want to set as link content
	 * @see ImageSt#getTxt
	 */
	this.setTxt = function(txt){
		_setTxt(txt);
	}

	/**
	 * return the link content. Link content can be a text string or an image    
	 * @returns the content of link (if an ImageSt is set it returns the corresponding &lt;img&gt; tag)
	 * @see ImageSt#setTxt
	 */	
	this.getTxt = function(){
		return linkTxt;
	}
	
	/**
	 * Sets the title of the &lt;a&gt; link tag  
	 * @param {String} title The value of title element property
	 * @see ImageSt#setClass
	 * @see ImageSt#setId
	 */
	this.setTitle = function(title){
		_setTitle(title);
	}
	
	/**
	 * Returns the html representation of this element 
	 * @example &lt;a  href="your_URL" id="optional id" class="opt class" title="opt title"&gt;link txt or image&lt;&#47;a&gt;   
	 * @returns An html string
	 * @see BaseWidget#render
	 */		
	this.toString = function(){
		var mytemp = "<a id=\""+ myid +"\" ";
		
		if(linkClass){
			mytemp += "class=\""+ linkClass +"\" ";
		}
		
		if(linkTitle){
			mytemp += "title=\""+ linkTitle +"\" ";
		}
		
		if(that.jsref){
			mytemp += " href=\"javascript:function preventchange(){return false;}\" >";
			$('#'+ myid).die("click");
			$('#'+ myid).live("click",that.jsref);
		}else if(that.href){
			mytemp += "href=\""+that.href+"\" >";
		}else{
		    return -1;
	    }
		
		mytemp += linkTxt+"</a>";
		return mytemp;
	}
	
}



// esempio di derivazione: TextWidget
/**
@class simple widget to display a custom text inside a &lt;div&gt; element. Is used as superclass for other text based widgets (I.E. forward and backward timers)
@augments BaseWidget
@param {String} Id widget id
*/
function TextWidget(Id){
    this.id = Id;
    this.param = new Param();
}
extend(TextWidget,BaseWidget);            // qui applico l'ereditarietà
                                          // (tipo java: class TextWidget extends BaseWidget)
TextWidget.prototype.innertext = "";      // aggiungo un nuovo attributo alla classe

/**
 * sets the innertext attribute
 * @param {String} txt text to which innertext must be set
 * @returns 0 if txt is a text string, -1 otherwise
 */
TextWidget.prototype.setInnerText = function(txt){  // aggiungo un metodo (che controlla e setta l'attributo)
    if(typeof txt == "string" ){
        this.innertext = txt;
        return 0;
    }else{
        return -1;
    }
};

/** @ignore */
TextWidget.prototype.getRenderString = function(){        // sovrascrivo la funzione render della classe BaseWidget
      return '<div id="'+this.id+'" style="' + this.printInlineStyle() + '">' +
      this.innertext + "</div>";
};

//----ButtonWidget widget----------------------------
/**
 * @class is exactly what its name suggests. 
 * @augments BaseWidget 
 * @param {Function} [fun] function to be executed on button click
 */
function ButtonWidget(Id,fun){
    this.id = Id;
    this.param = new Param();
    this.wFunction = fun;
}

extend(ButtonWidget,BaseWidget);
ButtonWidget.prototype.innertext = "";
ButtonWidget.prototype.backColor = "";

/**
 * sets the innertext attribute
 * @param {String} txt text to which innertext must be set
 * @returns 0 if txt is a text string, -1 otherwise
 */
ButtonWidget.prototype.setInnerText = function(txt){
    if(typeof txt == "string" ){
       this.innertext = txt;
       return 0;
    }else
       return -1;
};
/** @ignore */
ButtonWidget.prototype.fun = function(){
    alert(typeof this);
};

/** @ignore */
ButtonWidget.prototype.action = function(oggetto) {
    if(oggetto.wFunction instanceof Function){
        oggetto.wFunction();
    }
}

/** @ignore */
ButtonWidget.prototype.getRenderString = function(){
    return '<input id="' + this.id + '" type="button" style="' +
    this.printInlineStyle() + '" value="' + this.innertext + '"/>';
}

/** @ignore */
ButtonWidget.prototype.postRender = function() {
    var questo = this;
    $("#" + this.id).bind("click", function() { questo.action(questo); });
};



//----ImageWidget widget------------------
/**
@class lets the game developer show an image inside of his site. 
    <br/>The widget shows a spinner while the image is loading, and as soon as the image is fully loaded it's been displayed with a fade effect.
@augments BaseWidget
*/
function ImageWidget(Id){
    this.id = Id;
    this.param = new Param();
}

extend(ImageWidget,BaseWidget);

ImageWidget.prototype.uri = "";

/**
@param {String} txt an URI to an image file
@returns 0 if everything went OK, -1 otherwise
*/
ImageWidget.prototype.setUri = function(txt){ //DA CONTROLLARE
 /*   var exist = false;
    if(typeof txt == "string" ){
        $.ajax({
            url:txt, //funziona solo per file sullo stesso dominio
            type:'HEAD',
            success:function(risp){
                exist = true;
            },
            error:function(e){
                alert("Il file richiesto non esiste");
            }
        });
    } else return -1;*/
    this.uri=txt;
  /*  return 0;*/
};
ImageWidget.prototype.setImageObj = function(img_obj){
    return this.setUri(img_obj.getImageUri());
};

// sovrascrivo la funzione render della classe BaseWidget
/** @ignore */
ImageWidget.prototype.getRenderString = function(){
    var myimage = this.uri;
    var myid = this.id;
    var mywid = this.param.w;
    var myhei = this.param.h;
    // when the DOM is ready
    var img = new Image();

    // wrap our new image in jQuery, then:
    $(img).load(function() { // once the image has loaded, execute this code
        // set the div hidden by default    
        $('#' + myid).hide();
        // with the holding div #loader, apply:
        // then -> remove the loading class (so no background spinner), 
        // then -> insert our image
        $('#' + myid).removeClass('loading').append(this);

        //set same sizes both in image and div (image container)
        this.width = mywid;
        this.height = myhei;

        // fade our image in to create a nice effect
        if (!$.browser.msie) $('#' + myid).fadeIn();
        else $('#' + myid).show()
    })

    // if there was an error loading the image, react accordingly
    .error(function() {
        //alert("immagine non caricata");
        //this.removeClass('loading').append("errore nel caricamento dell'immagine");
    })

    // *finally*, set the src attribute of the new image to our image
    .attr('src', myimage);


    return "<div id=\"" + this.id + "\" style=\"width:" + this.param.w + "px; height: " + this.param.h + "px;" +
    this.printInlineStyle() + "\" ></div>";
};

// adding loading class
/** @ignore */
ImageWidget.prototype.postRender = function() {
    $('#' + this.id).addClass('loading');
}

//-------------timer widget---------------
/**
@class a forward timer. Starts from 0 and goes on until it's stopped
@augments TextWidget
*/
function TimerWidget(Id){
    this.id = Id;
    this.param = new Param();
}
 
extend(TimerWidget,TextWidget);
TimerWidget.prototype.time = 0;

TimerWidget.prototype.step = function(){
    now = new Date().getTime();
    now -= this.startT;
    inc = Math.floor(now/1000);
    this.startT += inc*1000;
    this.time += inc;
    this.doRender();
};

/**
Starts the timer when called
*/
TimerWidget.prototype.start = function(){
    var questo = this;
    this.startT = new Date().getTime();
    this.doRender();
    this.timerID = setInterval(function(){questo.step()}, 200);
};

/**
Stops the timer
@param {boolean} [kill] if true the callback function (if any) is not executed
*/
TimerWidget.prototype.stop = function(kill){
    if(this.timerID){
       clearInterval(this.timerID);
       if(this.callback && !kill)
          this.callback();
    }
};

/**
Sets a callback function to be executed when the timer is stopped
@param {Function} cb
*/
TimerWidget.prototype.setCallback = function(cb){
    if(cb instanceof Function)
       this.callback = cb;
}

/**
Removes the function to be executed on timer stop (if any)
*/
TimerWidget.prototype.deleteCallback = function(){
    this.callback = null;
}

TimerWidget.prototype.doRender = function(){ //for internal use
    $("#"+this.id).text(this.time+" secondi");
}


//------------countdown widget---------
/**
@class a countdown timer
@augments TimerWidget
*/
function CountdownWidget(Id){
    this.id = Id;
    this.param = new Param();
}

extend(CountdownWidget,TimerWidget);

CountdownWidget.prototype.step = function(){
    now = new Date().getTime();
    now -= this.startT;
    dec = Math.floor(now/1000);
    this.startT += dec*1000;
    this.time -= dec;
    this.doRender();
    if(this.time <= 0){
       this.stop(false);
    }
};

/**
Sets the time (in seconds) to be counted down
@param {Number} Time
@example cw.setRemainingTime(cw.getRemainingTime() + 10) // adds 10 seconds to the timer
@see getRemainingTime
*/
CountdownWidget.prototype.setRemainingTime = function(Time){
    this.time = Time;
}

/**
Returns the time (in seconds) to be counted down
@param {Number} Time
@see setRemainingTime
*/
CountdownWidget.prototype.getRemainingTime = function(){
    return this.time;
}


/** 
 *  @class The LoginWidget can be used to allow the game&#39;s access only at register users.  
 *  @augments BaseWidget
 *  @param {String} [id = Id] The Widget&#39;s identificator.
 *  @param {Function} [login_wfFunction = myCallback] Function associated to the button click.
 *  @param {String} [loginServer = Server] The Server name. 
*/
function LoginWidget(Id,Server,myCallback){
    this.id = Id;
    this.login_wfFunction = myCallback;
    this.loginServer = Server; 			//"Service1.asmx/Login"	 TEST
    this.param = new Param();
}

//widget extend BaseWidget
extend(LoginWidget, BaseWidget);

/** The result of the connection.
*   @field 
*   @type boolean
*   @default false
*/	
LoginWidget.prototype.connectionSuccess =  false;

/** The text for the Username Box.
*   @field 
*   @type String
*   @default "Username"
*/
LoginWidget.prototype.userText =  "Username";

/** The text for the Password Box.
*   @field 
*   @type String
*   @default "Password"
*/
LoginWidget.prototype.passText =  "Password";

/** The text in the submit button.
*   @field 
*   @type String
*   @default "login"
*/
LoginWidget.prototype.buttonText =  "login";

/** The Session Identificator.
*   @field 
*   @type String
*/
LoginWidget.prototype.loginSessionId = "";

/** The text that has to be appended under the password input box.
*   @field 
*   @type String
*/
LoginWidget.prototype.textToAppend = "";


/**
 * Set text that should be hung under password box.
 * <br/>Inside text is possible to insert one or more link putting a placeholder and writing some like this:
 * <br/>"Don't have an account yet?&lt;br&#47;&gt;Please [[register]]" if you want to set a link with "register" text.
 * Likewise printf() in C once you has put some link placeholder (syntax is: [[link text]]) you can pass as parameters
 * LinkSt or ImageSt object.
 * <br/>If a ImageSt object is passed this substitute corresponding placeholder text replacing it with ImageSt.toString() output. If placeholder contains some text this will overwrite text of the image tag. 
 * <br/>If a LinkSt object is passed this substitute corresponding placeholder text replacing it with LinkSt.toString() output. If placeholder contains some text this will overwrite text of the link. 
 * <br/><b>Note: </b> if there are no placeholder in first string parameter the original string is returned
 * <br/><b>Note: </b> the quantity of placeholders in first string must match the number of LinkSt/ImageSt object passed 
 * @param {string} txt the text that should be hung under password box (it may contains some link placeholder)
 * @returns {Integer} 0 if parameter are valid -1 otherwise
 * @see LoginWidget#setUserText
 * @see LoginWidget#setPassText
 * @see LoginWidget#setButtonText
 * @see BaseWidget#parseString
 * @example myLoginWidget.appendText("please [[register]] or [[go ahead]]",new Link("linkId",function(){alert("i'm a link!");}),new LinkSt("link_prova_2","http://www.yoursite.com/path_to_next_page","go ahead","dummyclass"));
 * @example myLoginWidget.appendText("please [[]]",new Link("linkId",function(){alert("i'm a link!");},"link_class","register"));
 */
LoginWidget.prototype.appendText = function(txt){
    /*for(var h=0; h < arguments.length; h++){
        this.str_args += h.toString() + ":" + arguments[h].toString();
        if(h != (arguments.length -1))
            this.str_args += ",";
    }*/
    var res = this.parseString(arguments);
    //eval("var res = this.parseString({txt});");
    if(res != -1){
        this.textToAppend = res;
        return 0;
    }
    return -1;
};
/**
 *  Function used to set the text of nickname box.
 *  @param {String} str The text that has to be set as label for username input
 *  @returns {Integer} 0 if parameter are valid -1 otherwise
*/
LoginWidget.prototype.setUserText = function(str){
   if(typeof str == "string"){
      this.userText = str;
      return 0;
   }
   return -1;
};		
/**
 *  Function used to set the text of password box.
 *  @param {String} str The text that has to be set as label for password input
 *  @returns {Integer} 0 if parameter are valid -1 otherwise
*/
LoginWidget.prototype.setPassText = function(str){
   if(typeof str == "string"){
      this.passText = str;
      return 0;
   }
   return -1;
},

/**
 *  Function used to set the submit button text.
 *  @param {String} str The text that has to be set as input button label 
 *  @returns {Integer} 0 if parameter are valid -1 otherwise
*/
LoginWidget.prototype.setButtonText = function(str){
   if(typeof str == "string"){
      this.buttonText = str;
      return 0;
   }
   return -1;
},

/**
 *  Function associated to the button click. 
 *  <br/>You can specify here the callback for the submit "click" event.
 *  <br/><b>Note:</b> you may want to use a WebService object to realize the comunication
 *  @param {Object} newFun The new callback function
 *  @returns {Integer} 0 if parameter are valid -1 otherwise
 *  @see LoginWidget#Validate
*/
LoginWidget.prototype.setLoginAction = function(newFun){			
   if(typeof newFun == "function"){
      this.login_wfFunction = newFun;
      return 0;
   }
   return -1;
      
}, 

/*
 *  Function that build login div HTML
 *  @returns {String} The HTML string associated to widget
 */
/** @ignore */
LoginWidget.prototype.getRenderString =  function(){
	return '<form action="javascript:" method="post" id="LoginForm_' + this.id + '"><div id="' + this.id + '" style="' + this.printInlineStyle() + '" >' +
            '<label>'+ this.userText +'</label><br/>' +
            '<span style="width:'+this.param.w +'px; padding-right:5px;" ><input id="userNick" type="text" /></span><br />' +
            '<label>'+ this.passText +'</label><br/>' +
            '<span style="margin-right:5px;" ><input id="userPass" type="password" /></span><br />' +
            '<input type="submit" id="LoginButton_' + this.id + '"  value="' + this.buttonText + '" ></input><br />' +
            this.textToAppend +
          '</div></form>';
};

/**
 *  Function that superficially validates username and password and call the button callback.
 *  It alerts the user only if one is null.
 *  After the initial validation login input box value is copied in the public User member 
 *  as well password input box value in Pass public member.
 *  @see LoginWidget#setLoginAction
 */
LoginWidget.prototype.Validate = function(){
    var that = this;
    var username = ($('#userNick').val() == "") ? '' : '"' + $('#userNick').val() + '"';
    if (username == '') return alert('Inseisci un nickname');
    var password = ($('#userPass').val() == "") ? '' : $('#userPass').val();
    if (password == '') return alert('Inserisci una password');
    that.User = username;
    that.Pass = password;
    that.login_wfFunction(that);
};


/** @ignore */
/*
    Function that bind "onclick" submit button event
    @param {Function} The function which is called when a "onclick" event occur
*/
LoginWidget.prototype.postRender = function() {
    var questo = this;
    //$("#LoginButton_" + this.id).bind("click", function() { questo.loginAction(questo); });
    $("#LoginForm_" + this.id).bind("submit", function() {
        questo.Validate(questo);
        return false;
    });
}

/**
    Function that unbind "onclick" submit button event
    @deprecated
*/
LoginWidget.prototype.preDelete = function() {
    var questo = this;
    $("#LoginButton_" + this.id).die("click", function() { questo.loginAction(questo); });
}

LoginWidget.prototype.deleteMe = function(){
    var that = this;
        $('#LoginForm_' + that.id).remove();
}



 //---------------List Box Widget---------------------
/** 
 *  @class The ListBox can be used to print list.
 *  With this widget you could create any kind of list (ordered, unordered, with an image as the list item marker, and so on) available at  xhtml+css   
 *  @augments BaseWidget
 *  @param {String} [id = Id] The Widget&#39;s identificator.
 *  @param {Function} [login_wfFunction = myCallback] Function associated to the button click.
 *  @param {String} [loginServer = Server] The Server name. 
*/
 function ListBox(Id, List, Title) {        // changed constructor method (implementing overload)
    this.list = [];
    switch(arguments.length){
        case 3:
            if(typeof arguments[2] === "string"){
                this.title = arguments[2];
            }
        case 2:
            if(arguments[1] instanceof Array){
                this.list = [];
                for(var i=0; i < arguments[1].length; i++){
                    this.addWord(arguments[1][i]);
                }
            }else if(typeof arguments[1] === "string"){
                this.title = arguments[1];
            }
        case 1:
            if(typeof arguments[0] === "string"){
               this.id = arguments[0];
            }
        break;
        default:
            alert("Error: not enough parameter in costructor ListBox!");
        break;
    }
    this.param = new Param();
	this.listType = "ul";
    this.listItemImage = false;
    this.listItemPlaceHolder = false;
 }
 extend(ListBox, TextWidget);
/** @ignore */
 ListBox.prototype.getRenderString = function() {
    var tmp_str = '<div id="' + this.id + '" style="' + this.printInlineStyle() +
        '"> <'+ this.listType + ' id="' + this.id + '_list"> '+ this.title;
    
	var iter = IteratorArray(this.list);
    try {
        while (iter.hasNext()){
            var item = iter.next();        
            tmp_str += '\n <li id="' + item.key + '_element_list"><div><label>' + item.value.txt+'</label>';
            if(item.value.add != undefined){
                tmp_str += this.parseString(item.value.add);
            }
            tmp_str += '</div></li>';
        }
    }
    catch (err) {
        if (err instanceof StopIteration);
    };
    /*for (var i = 0; i < this.list.length; i++){
        tmp_str += '\n <li id="' + i + '_element_list" >' + this.list[i].txt;
        if(this.list[i].add){
            tmp_str += this.parseString(this.list[i].add);
        }
        tmp_str += '</li>';
    }*/
    tmp_str += '</'+ this.listType + '> </div>';
    return tmp_str;
 }
 
 /** Set the new word list. 
  * To empty out the word list you can use this method without passing any paramenter
  * @param [Array] newlist the new word list if no list is specified function empty out the list
  * @returns {Integer} 0 if parameter are valid -1 otherwise
  * @see ListBox#addWord
  * @see ListBox#removeWord
  */
 ListBox.prototype.setWordList = function(newlist) {  
 
    if(arguments.length == 0){
        this.list = [];
        return 0;
    }else if(newlist instanceof Array){
        for(var i=0; i < newlist.length; i++){
           this.addWord(newlist[i]);
        }
        return 0;
    }
    return -1;
 }

/**
 * Adds a single string or an object that has "txt" and "add" field.
 * Adds to the wordlist one single element which can be a simple string,o an object that has to contains the txt field at list and optionally the add field.
 * <br/> The field "add", if specified, has to be an array and has to contain at least one string element, the first.
 * Besides the first string element, the other element of "add" has to be LinkSt or ImageSt object. 
 * <br/> The whole add field will be parsed by parseString() method and the redult of that will be appended before the end of the corresponding list item.
 * <br/><b>Note: </b> to apply the changes in DOM render() has to be called     
 * @param {String|Object} newelem String or an ImageSt/LinkSt object
 * @see BaseWidget#parseString
 * @see ListBox#removeWord
 * @see ListBox#setWordList
 */
 ListBox.prototype.addWord = function(newelem) { 
    if(typeof newelem == "string")
        this.list = [{txt:newelem}].concat(this.list);        
        
    else if(newelem.text != "undefined")
        this.list= [newelem].concat(this.list);

 } 
 

 /**
  * Removes an element or element set from the wordlist.
  * If a single index is specified, the corresponding element will be removed from wordlist.
  * <br/>If a couple of index are specified it will remove any element whose index is in the range specified by two indices.
  * <br/>If no index is not specified it will remove the last element of the wordlist.
  * <br/>this method returns one or an array of pointer to the element removed. 
  * <br/><b>Note: </b> if even one of the two index is wrong, -1 will be returned. 
  * <br/><b>Note: </b> to apply the changes in DOM render() has to be called.
  * @param {Integer} [index]    The index of the element to remove or (if index2 is specified) the first endpoint of the interval to remove	
  * @param {Integer} [index2]	The second endpoint of the interval to remove
  * @returns Pointer of removed elements (one or an array of) or -1 if parameter are invalid
  * @see ListBox#addWord
  * @see ListBox#setWordList
  */
 ListBox.prototype.removeWord = function(index,index2) { 
    if(typeof index == "number" && typeof index2 == "number" 
        && index < this.list.length && index >= 0 
        && index2 < this.list.length && index2 >= 1 
        && index2 > index && arguments.length >= 2){
                
        return this.list.splice(index,index2);
    }else if (typeof index == "number" 
        && index < this.list.length && index >= 0 
        && arguments.length == 1){
            
        return this.list.splice(index,1);
        
    }else if (arguments.length == 0){
        return this.list.pop();
    }
    
    return -1;
 } 
 
/**
 * Sets the type of the list.
 * The HTML list can be ordered or un-orderd.
 * @param {"ul"|"ol"} list_type the html type of the list
 * @returns {Integer} 0 if parameter are valid -1 otherwise
 */
 ListBox.prototype.setListType = function(list_type) {   
    var legal_par = " ul ol ";
    if(flag instanceof String && legal_par.indexOf(" " + list_type + " ") != -1){
        this.listType = list_type;
		return 0;    
    }
	return -1;
 }
 
/**
 * Sets the list item image.
 * You can specify an URL to set an image as item image or false value
 * @param {false|URL} image_url the url of the item list image
 * @returns {Integer} 0 if parameter are valid -1 otherwise
 */
 ListBox.prototype.setListItemImage = function(image_url) {   
    var regEx = /^([\\\/:a-zA-Z0-9_\-#\[\]\+]+\.[a-zA-Z]{3,})$/;
    
    if(typeof image_url == "string" && regEx.test(image_url)){
        this.listItemObj = image_url; 
        return 0;   
    }else if(typeof image_url == "boolean" && !image_url){
		this.listItemObj = image_url; 
        return 0;
	}
	
    return -1;
 }
 
/**
 * Sets the list item placeholder.
 * You can specify type of placeholder for list items.
 * @param {none|circle|disc|square|...} pholder The list items placeholder
 * @returns {Integer} 0 if parameter are valid -1 otherwise
 */
 ListBox.prototype.setItemPlaceHolder = function(pholder) {   
    var regEx = /^(none|circle|disc|square|armenian|decimal|decimal-leading-zero|georgian|lower-alpha|lower-greek|lower-latin|lower-roman|upper-alpha|upper-latin|upper-roman|inherit)$/;
    if((typeof pholder == "string" && regEx.test(pholder)) || (typeof pholder == "boolean")){
        this.listItemPlaceHolder = pholder;   
        return 0; 
    }
    
    return -1;
 }

/**
 * Sets the title of the list.
 * the title has to be a string and it will put on topo of the list with greater font size
 * @param {String} newtitle the list title
 * @returns {Integer} 0 if parameter are valid -1 otherwise
 */ 
 ListBox.prototype.setTitle = function(newtitle) {
    if(newtitle instanceof String){
        this.title = newtitle;
		return 0;
    }
    return -1;
 }
/** @ignore */
 ListBox.prototype.check = function (word) {
    var result = true;
    for (var i = 0; i < this.list.length; i++) {
       if (this.list[i].txt == word)
          result = false;
    }
    return result;
 }
 
 /** @ignore */
 ListBox.prototype.getWordIndex = function(word){   //method used to retrive index in word list
    var result = -1;
    
    for(var i = 0; i < this.list.length && result == -1; i++ ){
        result = this.list[i].txt == word ? i:-1;
    }
    
    return result;
 }
 
/**
 * Animates the selected word and call the callback and the end of animation.
 * A word or an index can be specified as first parameter. In the second case the word whose index corresponds to the specified one will be animated
 * @param {Integer|String} word The word to animate or its numerical index
 * @param {Function} callback The function that has to be called at the end of the animation
 */
 ListBox.prototype.alertElement = function(word,callback){  //method used to animate element
    
    if(typeof word === "string"){
        word = this.getWordIndex(word);
    }

    if(typeof word === "number" && word != -1){
        var wo = $("#" + word + "_element_list");
        if(wo){
            wo.animate({ 
                color: "#FF3300",
                fontSize: "200%"
              }, 500).animate({ 
                fontSize: "100%"
              }, 500,callback);
        }   
    }   
 }
 
 /** @ignore */
 ListBox.prototype.postRender = function() {

    if(this.listItemPlaceHolder)
        $("ul#" + this.id + "_list").css('list-style-type',this.listItemPlaceHolder); 
    else
        $("ul#" + this.id + "_list").css('list-style-type','disc'); 

    if(this.listItemImage)
        $("#" + this.id + "_list li").css('list-style-image','url(' + this.listItemImage + ')'); 
    else 
        $("#" + this.id + "_list li").css('list-style-image','none'); 
    
}

//--------- Input Box----------------------

/**
    This widget represent a in input text fielde lets the user send an arbitrary text input
    @class widget with base functionalities
    @constructor 
    @param {String} Id The id of the widget
    
 */
 function InputBox(Id, ButtonAction, Label, Ksend) {        // added Button Action
     this.id = Id;
     this.param = new Param();
     switch (arguments.length) {
         case 4:
             if (typeof Ksend == "boolean") {
                 this.keyboard = Ksend;
             }
             else break;
         case 3:
             if (typeof Label == "string") {
                 this.button = new ButtonWidget(Id + "_button", ButtonAction instanceof Function ? ButtonAction : null);
                 this.button.setInnerText(Label);
             }
//             else break;
//         case 2:
//             if (typeof Submit == "function") {
//                 //this.wFunction = Submit;
//             }
     }
 }

extend(InputBox, BaseWidget);

InputBox.prototype.result = function() {
    var result = $('#' + this.id + '_text').val();
    return result;
}

InputBox.prototype.clickReset = false;

InputBox.prototype.setClickReset = function(bool) {
    if (typeof bool == "boolean") {
        this.clickReset = bool;
    }
}

InputBox.prototype.clear = function() {
    var id = this.id;
    this.bind("click", function() {
        //alert('#' + id + '_text '+ this);
        $('#' + id + '_text').val('');
    });
}

/** @ignore */
InputBox.prototype.getRenderString = function() {//aggiunto width se no non funziona 
    return '<div id="' + this.id + '" style="' + this.printInlineStyle() +
         '" > <form id="' + this.id + '_form" action="javascript:" > \n <input id="' +
         this.id + '_text" type="text" style="left:' + this.param.x +
         'px; top:0px; position:absolute; width:250px" &frasl;>  </form> </div>';
}

/** @ignore */
InputBox.prototype.postRender = function() {
    var dimTex = parseInt($("#" + this.id + "_text").css('width')); //in inputbox_text non c'e il width
    dimTex = Math.round(dimTex / this.DIM_GRIGLIA);
    this.button.setDimension(10, 5);
    this.button.setPosition(this.param.x / this.DIM_GRIGLIA + dimTex + 3, 0);
    this.button.render(this.id + "_form");
    if (this.clickReset) { this.clear(); }
}





//------------status widget---------
/** @ignore */
function StatusWidget(Id, myNick, myLogOut, url, score) {
    this.id = Id;
    this.score = new TextWidget(Id + "_score");
    this.image = new ImageWidget(Id + "_image");
    this.nick = new TextWidget(Id + "_text");
	this.button = null;
    this.sc = 0;
    switch (arguments.length) {
        case 5:
            if (typeof score == "number") {
                this.score.setInnerText('Score :' + score.toString());
                this.sc = score;
            }
            else break;
        case 4:            
            if (typeof url == "string") {
                
                this.image.setUri(url);                
            }
            else break;
        case 3:
            this.button = new ButtonWidget(Id + "_logout", myLogOut instanceof Function ? myLogOut : null);            
            this.button.setInnerText('Logout');

        case 2:
            if (typeof myNick == "string") {                
                this.nick.setInnerText(myNick.toString());
            } 
                     
    }
    this.param = new Param();
}

//widget extend BaseWidget
extend(StatusWidget, BaseWidget);

/** @ignore */
StatusWidget.prototype.setNickText = function(str) {
    if (typeof str == "string")
        this.nick.setInnerText(str.toString());
}
/** @ignore */
StatusWidget.prototype.setScoreText = function(str) {
    if (typeof str == "number") {
        this.sc += str;
        $("#" + this.id + "_score").text('Score :'+this.sc);
        this.score.setInnerText('Score :' + str.toString());
    }
}
/** @ignore */
StatusWidget.prototype.setUriImage = function(str) {
    if ((this.image != undefined) && (this.image != null) && (str == "string"))
        this.image.setUri(str);
}

/** @ignore */
StatusWidget.prototype.getRenderString = function() {
    this.score.setPosition(4, 6);
    this.score.setFont(20);
    this.nick.setPosition(4, 0);
    this.nick.setFont(20);
    this.image.setPosition(5, 0);
    this.image.setDimension(10, 10);
   	if(this.button)
        this.button.setPosition(7, 11);
    if(this.button)
        var bhtml = this.button.getRenderString();
    else
        var bhtml = "";
    //this.button.setDimension(8, 4)
    return '<div id="' + this.id + '" style="' + this.printInlineStyle() + 'position:relative;" >' +
            '<span style="width:' + this.param.w + 'px; padding-right:5px;" >' + this.image.getRenderString() + '</span><br />' +
			bhtml + '<br />' +
            '<span style="width:' + this.param.w + 'px; padding-right:5px; color:#9ACD32" ><b>' + this.nick.getRenderString() + '</b></span><br />' +
            '<span style="width:' + this.param.w + 'px; padding-right:5px; color:#FF4040" ><b>' + this.score.getRenderString() + '</b></span><br />' +
          '</div>';
};

//change .live to .bind
/** @ignore */
StatusWidget.prototype.postRender = function() {
    this.image.postRender();
    if(this.button)
		this.button.postRender();
    //this.nick.showMe("slow");
    this.nick.fadeInMe("slow");
    //this.score.showMe("slow");
    this.score.fadeInMe("slow");
}

/**
* @class A widget containing a variable number of fields, used to collect data required to register new users.
* Four kind of fields are supported: text input, password input, dropdown menu and datepicker.
* @augments BaseWidget
* @param {String} Id the ID of the element. Must be unique to avoid strange behaviours from the web page.
* @param {Function} sendFunction is the function to be called when the user clicks the submit button.
*/
function RegisterWidget(Id, sendFunction){
    this.id = Id;
    this.param = new Param();
    this.fields = '';
    this.postRenders = new Array();
    this.mFields = new Array(); //id dei campi obbligatori
    this.validators = new Array();
    this.snd = sendFunction;
}
extend(RegisterWidget,BaseWidget);

/** @ignore */
RegisterWidget.prototype.getRenderString = function(){
  ret = '<div id="'+this.id+'" style="' + this.printInlineStyle() + '">' + this.fields + '<div id="'+this.id+'_submit"></div>';
  this.fields = null; // libero memoria
  return ret;
}

/** @ignore */
RegisterWidget.prototype.postRender = function() {
    var iter2 = IteratorArray(this.postRenders);
    try {
        var item2;
        while (iter2.hasNext()) {
            item2 = iter2.next();
            this.postRenders[item2.key]();
        }
    }
    catch (err) {
        if (err instanceof StopIteration);
    };

    this.postRenders = null; // libero memoria
    
    var f = this.mFields;
    var v = this.validators;
    /** @ignore */
    var checkfunc = function() {
        var iter = IteratorArray(f);
        try {
            var item;
            while (iter.hasNext()) {
                item = iter.next();
                if ($('#' + item.key).val() == '') {
                    alert('campo vuoto');
                    return false;
                }
            }
        }
        catch (err) {
            if (err instanceof StopIteration);
        };
        
        var iter2 = IteratorArray(v);
        try {
            var item;
            while (iter2.hasNext()) {
                item = iter2.next();
                if ($('#' + item.key).val() != '' && $('#' + item.key + '_valid').text() != 'Ok') {
                    alert(item.key);
                    alert($('#' + item.key + '_valid').text());
                    return false;
                }
            }
        }
        catch (err) {
            if (err instanceof StopIteration);
        };
        
        return true;
    };
    var that = this;
    var submit = new ButtonWidget(this.id + '_button', function() {
        if (checkfunc()) {
            that.snd();
        }
        else
            alert('Alcuni campi non sono corretti. Verificare');
    });
    submit.setInnerText('Submit');
    submit.render(this.id + '_submit');
    $('#' + this.id + '_submit').css("position", "relative");
}

/**
* @description adds a new field to the widget. Must be called before the widget is rendered.
* @param {String} Id an identifier for the field. Must be unique inside the widget. <br />
* If the widget has &quot;id1&quot; as ID and the field is created with ID &quot;id2&quot;
* than the ID of the field willl be &quot;id1_id2&quot;
* @param {String} label text displayed before the relative field, describes to the user what
* data you expect him to insert.
* @param {Array} parameters a list of properties relative to the type of field you are creating<br />
* The fields expected to be into the array are: <br /><code>
* type ::= &quot;drop&quot; | &quot;pass&quot; | &quot;date&quot; | &quot;input&quot;<br />
* indicates the type of the field. If the field &quot;id2&quot; of the widget &quot;id1&quot;
* is of type &quot;type&quot; you can access his value calling $(&quot;#id1_id2_type&quot;).val()<br />
* validator ::= Function: ID -> String<br />
* The validator is an optional function which checks client-side the correctness of the data inserted into the field.
* Takes in input the ID of the field to be checked and must return a text string containing an error message
* to be shown to the user if the test fails, &quot;Ok&quot; otherwise.<br />
* mandatory ::= true | false<br />
* Is an optional parameter, says if the field must be filled or can be left blank. The default
* value for <b>mandatory</b> is <b>false</b>.
* If the type is &quot;drop&quot; you have also the following parameter:<br />
* options ::= Array<br />
* It's an array of strings listing all the options available<br />
* If the type is &quot;drop&quot; you have also the following parameters:<br />
* start, end, show ::= String<br />
* The three parameters are optional; the first specifies the minimumdate selectable with the datepicker,
* the second the last date, the third the date selected by default on calendar opening. The three dates are
* strings in the dd/mm/yyyy format, or a number of days from today (e.g. +7) or a string of values and periods
* ('y' for years, 'm' for months, 'w' for weeks, 'd' for days, e.g. '+1m +7d'). Default values are
* &quot;25 years ago&quot; for <b>start</b>, &quot;50 years ago&quot; for <b>start</b>, &quot;today&quot;
* for <b>end</b>
* </code>
* @example x = new RegisterWidget(&quot;reg&quot;, null); 
* x.addField(&quot;ciao&quot;, &quot;Password&quot;, {type: &quot;pass&quot;, mandatory: true, validator: function(id)
* {if($(&quot;#&quot;+id).val().length &lt; 6) return &quot;The password is too short&quot;; else return
* &quot;Ok&quot;}});
* x.addField(&quot;nascita&quot;, &quot;Data di nascita&quot;, {type: &quot;date&quot;, mandatory: true,
* start: &quot;13/07/1975&quot;, end: &quot;-3w+2d&quot;});
* x.addField(&quot;dove&quot;, &quot;Nazionalit&agrave;&quot;, {type: &quot;drop&quot;, options :
* {&quot;Tunisia&quot;, &quot;Belize&quot;, &quot;Stato libero di Bananas&quot;, &quot;Apolide&quot;}});
*/
RegisterWidget.prototype.addField = function(Id, label, parameters){
	var myid = this.id+"_"+Id;
	var myid2 = myid+'_'+parameters.type;
	var externaldiv = '<div id="' + myid + '" style="' + this.printInlineStyle() + '" >';
	var lab = '<label>'+ label+':';
	if(parameters.mandatory){
		this.mFields[myid2] = myid2+"_valid";
		lab += '<span class=mandatory_symbol>*</span>';
	}
	lab += '</label><br/>';
	
	var str = this.getInternalString(myid2, label, parameters);
	if(parameters.validator instanceof Function){
		this.validators[myid2] = function(){parameters.validator(myid2)};
	} else{
		this.validators[myid2] = function(){return "Ok"};
	}
	
	this.fields += externaldiv + lab + str + '</div><br />';
	
	this.postRenders.push(function(){$('#'+myid).css("position", "relative");});
	var x = parameters.validator || V_fake;
	var m = this.mFields[myid2] || false;
	this.postRenders.push(function(){
		$('#'+myid2).blur(function(){
			var v = x(myid2);
			if(v === "Ok"){
				if(!m || $('#'+myid2).val() != ''){
					$('#'+myid2).removeClass("wrong");
					$('#'+myid2+'_valid').text(v);
				} else if (m){ //campo obbligatorio corretto ma vuoto
					$('#'+myid2).addClass("wrong");
					$('#'+myid2+'_valid').text("Campo obbligatorio!");
				}
			} else { // campo non corretto
				if(!m && $('#'+myid2).val() === ''){ // non obbligatorio e vuoto: OK
					$('#'+myid2).removeClass("wrong");
					$('#'+myid2+'_valid').text('');
				} else { // non vuoto: KO
					$('#'+myid2).addClass("wrong");
					$('#'+myid2+'_valid').text(v);
				}
			}
		})
	});
}

/**
* @description creates the HTML string of a single field
* @private
*/
RegisterWidget.prototype.getInternalString = function(myid, label, parameters) {
    var str = '<span style="width:' + this.param.w + 'px;padding-right:5px;" >';
    switch (parameters.type) {
        case "drop":
            str += '<select name="' + label + '" id="' + myid + '" ><option></option>';
            var iter = IteratorArray(parameters.options);
            try {
                while (iter.hasNext())
                    str += '<option>' + (iter.next()).value + '</option>';
            }
            catch (err) {
                if (err instanceof StopIteration);
            };
            
            str += '</select>';
            break;
        case "pass":
            str += '<input id="' + myid + '" type="password" />';
            break;
        case "date":
            var def = parameters.show || '-25y';
            var st = parameters.start || '-50y';
            var en = parameters.end || '+0';
            this.postRenders.push(function() {
                $('#' + myid).datepicker({
                   defaultDate: def,
                   minDate: st,
                   maxDate: en,
                   beforeShow: function(){$('#'+myid).val('')}
                })
            });
            str += '<input id="' + myid + '" type="text" readonly="readonly" />';
            break;
        case "input":
        default:
            str += '<input id="' + myid + '" type="text" />';
    }
    str += '<div id="' + myid + '_valid" style="display:inline-block;background-color:inherit;position:static;"></div>';
    return str + '</span>';
}

/**
* @description This method is called after a server-side check of the values submitted, only if
* some value is incorrect or rejected.
* @param {Array} errors an array in the form &quot;id of the wrong field&quot;:&quot;message to be
* shown to the user&quot;
* @example if the field with id &quot;id2&quot; of the widget w with id &quot;id1&quot; of type &quot;input&quot;
* is incorrect because it contains a nickname already used by someone else than the call is: <br />
* <b>w.verify({&quot;id1_id2_input&quot;:&quot;Nickname already in use&quot;});</b>
*/
RegisterWidget.prototype.verify = function(errors){
	for(var x in errors){
		$('#'+x).addClass('wrong');
		$('#'+x+'_valid').text(errors[x]);
	}
}
/** @ignore */
var P_input = {
	/** @ignore */
	mandatory: true,
	/** @ignore */
	type: "input",
	/** @ignore */
	validator: function(){return "Ok";}
};

/** @ignore */
var P_pass = {
	/** @ignore */
	mandatory: true,
	/** @ignore */
	type: "pass",
	/** @ignore */
	validator: ""//aggiungere validatore serio di default
}

/** @ignore */
var V_fake = function(){return "Ok";};
/** @ignore */
var V_never = function(){return "Failure";};

$.datepicker.setDefaults({
		closeText: 'Chiudi',
		prevText: '&#x3c;Prec',
		nextText: 'Succ&#x3e;',
		currentText: 'Oggi',
		monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
			'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
		monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',
			'Lug','Ago','Set','Ott','Nov','Dic'],
		dayNames: ['Domenica','Luned&#236','Marted&#236','Mercoled&#236','Gioved&#236','Venerd&#236','Sabato'],
		dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
		dayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],
		weekHeader: 'Sm',
		dateFormat: 'dd/mm/yy',
		firstDay: 1,
		isRTL: false,
		showMonthAfterYear: false,
		yearSuffix: '',
      showOn: 'button',
      buttonImageOnly: true,
      buttonImage: 'images/icon_cal.png',
      showOtherMonths: true,
      changeMonth: true,
      changeYear: true,
      showButtonPanel: true
   });

/**
* @class An help button (or link) which can be inserted next to a chosen element,
* showing a modal popup help window when clicked. The popup is closed by clicking anywhere
* outside the popup window
* @param {String} Id the ID of the help widget. Must be unique in the whole document
* @param {Array} properties an array of customizable parameters.<br />
* The fields looked for in the array are:<br />
* <code>button ::= String | ImageWidget<br />
* Is the text or image to be clicked for the popup to be shown<br />
* content ::= String | Array<br />
* A text string with the help message displayed inside the popup, or an array to be used as
* argument for the {@link BaseWidget#parseString} method.
* attach ::= String<br />
* the ID of the element, followed by an optional selector, to which the help button should be put beside
* </code>
* @example asd = new RegisterWidget(&quot;ciao&quot;, function(){alert(&quot;sending&quot;)});
* asd.addField(&quot;nick&quot;, &quot;Nickname&quot;, {type:&quot;input&quot;, mandatory:true});
* sos = new HelpWidget(&quot;nckhlp&quot;, {content:&quot;A nickname is the namen displayed in the site.
* A valid nick can contain only alphanumeric charachters.&quot;, button:&quot;Help me&quot;,
* attach:&quot;ciao_nick label&quot;});
*/
function HelpWidget(Id, properties){
   this.id = Id;
   this.param = new Param();
   $.extend(this.param, properties);
   this.shown = false;
}
extend(HelpWidget,BaseWidget);

/**@private*/
HelpWidget.prototype.getRenderString = function(){
   var cntt = '<div id="'+this.id+'_help_pwin">'+
      this.parseString(this.param.content)+'</div>'; //popup vero e proprio
   var bgr = '<div id="'+this.id+'_help_back"></div>'; //background nero
   return cntt+bgr;
}

/**@private*/
HelpWidget.prototype.postRender = function(){
   var tasto = $('<span></span>');
   tasto.attr('id', this.id+'_help');
	tasto.addClass('helpbutton');
   if(typeof this.param.button == 'string'){
      tasto.text(this.param.button);
   }
   else if(this.param.button instanceof ImageWidget){
      this.param.button.render(this.id+'_help');
   }
   else
      alert('bottone help sbagliato');

	tasto.css('display', 'inline');
   $('#'+this.param.attach).append(tasto);
   var questo = this;
   tasto.click(function(){questo.showPopup()});
	$("#"+this.id+'_help_back').click(function(){questo.hidePopup()});

	var backstyle = {
		'display':'none',
		'position':'fixed',
		'height':'100%',
		'width':'100%',
		'top':'0',
		'left':'0',
		'background':'#000000',
		'border':'1px solid #cecece',
		'z-index':'1'
   };

   var contentstyle = {
		'display':'none',
		'position':'fixed',
		'background':'#FFFFFF',
		'border':'2px solid #cecece',
		'z-index':'2'
   };

	$("#"+this.id+'_help_back').css(backstyle);
	$("#"+this.id+'_help_pwin').css(contentstyle);
}

/**
* @description the function which actually shows the popup
* @private
*/
HelpWidget.prototype.showPopup = function(){
   if(!this.shown){
      $("#"+this.id+'_help_back').css({
      "opacity": "0.7"
      });
      $("#"+this.id+'_help_back').fadeIn("slow");
      $("#"+this.id+'_help_pwin').fadeIn("slow");

		var windowWidth = $(document).width();
		var windowHeight = $(document).height();
		var popupHeight = $("#"+this.id+'_help_pwin').height();

		$("#"+this.id+'_help_pwin').css({
			"position": "absolute",
			"max-width": windowWidth/3,
			"top": windowHeight/2-popupHeight/2
		}).css('left', (windowWidth-$("#"+this.id+'_help_pwin').width())/2);
      this.shown = true;
	}
}

/**
* @description Hides the popup when called.
* @private
*/
HelpWidget.prototype.hidePopup = function(){
	if(this.shown){
		$("#"+this.id+'_help_back').fadeOut("slow");
		$("#"+this.id+'_help_pwin').fadeOut("slow");
		this.shown = false;
	}
}
